package ui;

import java.awt.Shape;
import java.awt.geom.Path2D;
import java.awt.geom.RoundRectangle2D;
import java.util.Random;

public class SpreadingCover extends Path2D.Float {

	private long refreshRate = 30;
	private int x, y, width, height;
	private RoundRectangle2D.Float unit = new RoundRectangle2D.Float(0, 0, 6, 6, 0, 0);
	private int[][] remainToFill;
	private int remainings;
	private Random rnd = new Random();

	private boolean stop, pause;

	private class MovieThread extends Thread {
		@Override
		public void run () {
			int round = 0;
			while (!stop) {
				try {
					while (pause) {
						Thread.sleep(1);
					}
					if (remainings == 0) {
						stop = true;
						return;
					}
					for (int i = 0; i < Math.min(3 * round, remainings); i++) {
						int r = rnd.nextInt(remainings);
						int[] coords = remainToFill[r];
						unit.setFrame(coords[0], coords[1], 6, 6);
						append(unit);
						remainToFill[r][0] = remainToFill[remainings - 1][0];
						remainToFill[r][1] = remainToFill[remainings - 1][1];
						remainings--;
					}
					Thread.sleep(refreshRate);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				round++;
			}
			stop = true;
		}
	}

	private Thread movie = new MovieThread();

	public SpreadingCover (int x, int y, int width, int height, Path2D init) {
		setWindingRule(WIND_NON_ZERO);
		append(init);
		this.x = x;
		this.y = y;
		this.width = width - 3;
		this.height = height - 3;
		remainToFill = new int[this.height * this.width / 9][2];
		for (int i = 0; i < this.height; i += 3) {
			for (int j = 0; j < this.width; j += 3) {
				if (!contains(x + j + 3, y + i + 3)) {
					remainToFill[remainings][0] = x + j;
					remainToFill[remainings][1] = y + i;
					remainings++;
				}
			}
		}
	}

	public synchronized void append (Shape s) {
		super.append(s, false);
	}

	public boolean isStopped () {
		return !movie.isAlive();
	}

	public void stop () {
		stop = true;
	}

	public void pause () {
		pause = true;
	}

	public void resume () {
		pause = false;
	}

	public void start () {
		if (movie.getState().equals(Thread.State.NEW)) {
			movie.start();
		}
	}

	public int getX () {
		return x;
	}

	public int getY () {
		return y;
	}

}
